package cn.sky.demo.utils;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
  * @author code4crafter@gmail.com
  * Date: 17/3/27
  */
public abstract class HttpClientUtils {

      public static Map<String, List<String>> convertHeaders(Header[] headers) {
            Map<String, List<String>> results = new HashMap<String, List<String>>();
             for  (Header header : headers) {
                  List<String> list = results.get(header.getName());
                   if  (list == null) {
                        list = new ArrayList<String>();
                        results.put(header.getName(), list);
                  }
                  list.add(header.getValue());
            }
             return  results;
      }

      /**
        * http的get请求
        * @param url
        */
      public static String get(String url) {
             //return  get(url,  "UTF-8");
          return get(url, createDefaultHeaders());
      }

      public static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
    public static String get(String url, Map<String, String> headers) {
        // 在现有 get 方法基础上添加 headers 参数处理
        // 示例代码：
        try {
            HttpGet httpGet = new HttpGet(url);
            // 添加请求头
            if (headers != null) {
                headers.forEach(httpGet::setHeader);
            }

            CloseableHttpClient httpClient = createSSLInsecureClient();
            CloseableHttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            return EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static Map<String, String> createDefaultHeaders() {
        Map<String, String> headers = new HashMap<>();
        headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");
        headers.put("Referer", "https://pic.sogou.com/");
        headers.put("Accept", "application/json, text/plain, */*");
        headers.put("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
        return headers;
    }
      /**
        * http的get请求
        * @param url
        */
      public static String get(String url, String charset) {
            HttpGet httpGet = new HttpGet(url);
             return  executeRequest(httpGet, charset);
      }

      /**
        * http的get请求，增加异步请求头参数
        * @param url
        */
      public static String ajaxGet(String url) {
             return  ajaxGet(url,  "UTF-8");
      }

      /**
        * http的get请求，增加异步请求头参数
        *
        * @param url
        */
      public static String ajaxGet(String url, String charset) {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("X-Requested-With",  "XMLHttpRequest");
             return  executeRequest(httpGet, charset);
      }

      /**
        * @param url
        * @return
        */
      public static String ajaxGet(CloseableHttpClient httpclient, String url) {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("X-Requested-With",  "XMLHttpRequest");
             return  executeRequest(httpclient, httpGet,  "UTF-8");
      }

      /**
        * http的post请求，传递map格式参数
        */
      public static String post(String url, Map<String, String> dataMap) {
             return  post(url, dataMap,  "UTF-8");
      }

      /**
        * http的post请求，传递map格式参数
        */
      public static String post(String url, Map<String, String> dataMap, String charset) {
            HttpPost httpPost = new HttpPost(url);
            try {
                   if  (dataMap != null) {
                        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                         for  (Map.Entry<String, String> entry : dataMap.entrySet()) {
                              nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                        }
                        UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, charset);
                        formEntity.setContentEncoding(charset);
                        httpPost.setEntity(formEntity);
                  }
            } catch (UnsupportedEncodingException e) {
                  e.printStackTrace();
            }
             return  executeRequest(httpPost, charset);
      }

      /**
        * http的post请求，增加异步请求头参数，传递map格式参数
        */
      public static String ajaxPost(String url, Map<String, String> dataMap) {
             return  ajaxPost(url, dataMap,  "UTF-8");
      }

      /**
        * http的post请求，增加异步请求头参数，传递map格式参数
        */
      public static String ajaxPost(String url, Map<String, String> dataMap, String charset) {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("X-Requested-With",  "XMLHttpRequest");
            try {
                   if  (dataMap != null) {
                        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                         for  (Map.Entry<String, String> entry : dataMap.entrySet()) {
                              nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                        }
                        UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, charset);
                        formEntity.setContentEncoding(charset);
                        httpPost.setEntity(formEntity);
                  }
            } catch (UnsupportedEncodingException e) {
                  e.printStackTrace();
            }
             return  executeRequest(httpPost, charset);
      }

      /**
        * http的post请求，增加异步请求头参数，传递json格式参数
        */
      public static String ajaxPostJson(String url, String jsonString) {
             return  ajaxPostJson(url, jsonString,  "UTF-8");
      }

      /**
        * http的post请求，增加异步请求头参数，传递json格式参数
        */
      public static String ajaxPostJson(String url, String jsonString, String charset) {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("X-Requested-With",  "XMLHttpRequest");
             
            StringEntity stringEntity = new StringEntity(jsonString, charset);// 解决中文乱码问题
            stringEntity.setContentEncoding(charset);
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
             return  executeRequest(httpPost, charset);
      }

      /**
        * 执行一个http请求，传递HttpGet或HttpPost参数
        */
      public static String executeRequest(HttpUriRequest httpRequest) {
             return  executeRequest(httpRequest,  "UTF-8");
      }

      /**
        * 执行一个http请求，传递HttpGet或HttpPost参数
        */
      public static String executeRequest(HttpUriRequest httpRequest, String charset) {
            CloseableHttpClient httpclient;
             if  ("https".equals(httpRequest.getURI().getScheme())) {
                  httpclient = createSSLInsecureClient();
            }  else  {
                  httpclient = HttpClients.createDefault();
            }
            String result =  "";
            try {
                  try {
                        CloseableHttpResponse response = httpclient.execute(httpRequest);
                        HttpEntity entity = null;
                        try {
                              entity = response.getEntity();
                              result = EntityUtils.toString(entity, charset);
                        } finally {
                              EntityUtils.consume(entity);
                              response.close();
                        }
                  } finally {
                        httpclient.close();
                  }
            } catch (IOException ex) {
                  ex.printStackTrace();
            }
             return  result;
      }

      public static String executeRequest(CloseableHttpClient httpclient, HttpUriRequest httpRequest, String charset) {
            String result =  "";
            try {
                  try {
                        CloseableHttpResponse response = httpclient.execute(httpRequest);
                        HttpEntity entity = null;
                        try {
                              entity = response.getEntity();
                              result = EntityUtils.toString(entity, charset);
                        } finally {
                              EntityUtils.consume(entity);
                              response.close();
                        }
                  } finally {
                        httpclient.close();
                  }
            } catch (IOException ex) {
                  ex.printStackTrace();
            }
             return  result;
      }

      /**
        * 创建 SSL连接
        */
      public static CloseableHttpClient  createSSLInsecureClient() {
            try {
                  SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(new  TrustStrategy() {
                        @Override
                        public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                               return  true;
                        }
                  }).build();
                  SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new  HostnameVerifier() {
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                               return  true;
                        }
                  });
                   return  HttpClients.custom().setSSLSocketFactory(sslsf).build();
            } catch (GeneralSecurityException ex) {
                  throw new RuntimeException(ex);
            }
      }
}